package com.bsj.sipgateway.web.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bsj.power.common.config.exception.ApiException;
import com.bsj.power.common.config.global.JsonResult;
import com.bsj.power.common.config.global.JsonResultEnum;
import com.bsj.power.common.config.global.TokenUser;
import com.bsj.power.common.config.redis.RedisConstant;
import com.bsj.power.common.def.dto.AttentionDTO;
import com.bsj.power.common.def.dto.RedisDeviceInfo;
import com.bsj.power.common.def.entity.Attention;
import com.bsj.power.common.def.entity.AttentionDevice;
import com.bsj.power.common.def.entity.gb28181.Device;
import com.bsj.power.common.def.entity.gb28181.DeviceChannel;
import com.bsj.power.common.def.vo.AttentionVO;
import com.bsj.power.common.def.vo.DeviceVO;
import com.bsj.power.common.mapper.AttentionDeviceMapper;
import com.bsj.power.common.mapper.AttentionMapper;
import com.bsj.power.common.mapper.DeviceChannelMapper;
import com.bsj.power.common.mapper.DeviceMapper;
import com.bsj.power.common.util.StpLoginUserUtil;
import com.bsj.sipgateway.common.constant.Constants;
import com.bsj.sipgateway.web.service.AttentionService;
import com.github.pagehelper.util.StringUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.bsj.JedisClusterBSJ;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description
 * @Author zhaoyang
 * @Date 2024/9/2 16:31
 */
@Service("attentionServiceImpl")
public class AttentionServiceImpl implements AttentionService {

    @Autowired
    private AttentionMapper attentionMapper;

    @Autowired
    private AttentionDeviceMapper attentionDeviceMapper;

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private JedisClusterBSJ jedisClusterBSJ;

    @Autowired
    private DeviceChannelMapper deviceChannelMapper;

    /**
     * 摄像头关注/取消关注
     *
     * @param did  设备数据库id
     * @param type 操作类型 1是关注0是取消关注
     * @return
     */
    @Override
    public JsonResult deviceAttention(Long did, Integer type) {
//        Device device = new Device();
//        device.setId(did);
//        device.setAttention(type);
//        deviceMapper.updateById(device);

        TokenUser tokenUser = StpLoginUserUtil.getTokenUser();
        if (tokenUser == null) {
            throw new ApiException(JsonResultEnum.FAIL, "无法获取登录用户信息，请重试");
        }
        Long userId = tokenUser.getUserId();

        if (type == 1) {
            // 关注的时候默认添加到该用户的默认目录
            Attention attention = attentionMapper.selectOne(Wrappers.<Attention>lambdaQuery().eq(Attention::getAttentionName, "默认分组")
                    .eq(Attention::getUid, userId));
            Integer aid = null;
            if (attention != null) {
                aid = attention.getId();
            } else {
                Attention newAttention = new Attention();
                newAttention.setAttentionName("默认分组");
                newAttention.setUid(userId.intValue());
                attentionMapper.insert(newAttention);
                aid = newAttention.getId();
            }

            AttentionDevice attentionDevice = new AttentionDevice();
            long id = did;
            attentionDevice.setDid((int) id);
            attentionDevice.setAid(aid);
            attentionDeviceMapper.insert(attentionDevice);
        } else if (type == 0) {
            // 取消关注的时候，把该用户关注目录里的设备删掉，在该用户所有目录里取消这个关系
            List<Attention> attentions = attentionMapper.selectList(Wrappers.<Attention>lambdaQuery().eq(Attention::getUid, userId));
            if (!CollectionUtils.isEmpty(attentions)) {
                for (Attention attention : attentions) {
                    Integer aid = attention.getId();
                    attentionDeviceMapper.delete(Wrappers.<AttentionDevice>lambdaQuery().eq(AttentionDevice::getAid, aid)
                            .eq(AttentionDevice::getDid, did));
                }
            }
        }

        return JsonResult.success();
    }


    @Override
    public JsonResult update(AttentionDTO attentionDTO) {
        QueryWrapper<Attention> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("attention_name", attentionDTO.getAttentionName());
        Attention attention1 = attentionMapper.selectOne(queryWrapper);
        if (attention1 != null && !attention1.getId().equals(attentionDTO.getId())) {
            throw new ApiException(JsonResultEnum.PARAM_ERROR, "名称重复，不能修改");
        }

        Attention attention = new Attention();
        BeanUtils.copyProperties(attentionDTO, attention);

        // 修改
        attentionMapper.updateById(attention);

        return JsonResult.success();
    }

    @Override
    public JsonResult add(AttentionDTO attentionDTO) {
        QueryWrapper<Attention> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("attention_name", attentionDTO.getAttentionName());
        Attention attention1 = attentionMapper.selectOne(queryWrapper);
        if (attention1 != null) {
            throw new ApiException(JsonResultEnum.PARAM_ERROR, "名称重复，不能添加");
        }

        Attention attention = new Attention();
        BeanUtils.copyProperties(attentionDTO, attention);
        if (attention.getUid() == null) {
            TokenUser tokenUser = StpLoginUserUtil.getTokenUser();
            if (tokenUser == null) {
                throw new ApiException(JsonResultEnum.FAIL, "无法获取登录用户信息，请重试");
            }
            attention.setUid(tokenUser.getUserId().intValue());

        }
        // 新增
        attentionMapper.insert(attention);

        return JsonResult.success();


    }

    @Override
    public JsonResult delete(Integer attentionId) {
        if (attentionId == 1) {
            throw new ApiException(JsonResultEnum.PARAM_ERROR, "默认目录不能删除");
        }
        // 查询这个分组中所有的绑定关系
        List<AttentionDevice> attentionDevices = attentionDeviceMapper
                .selectList(Wrappers.<AttentionDevice>lambdaQuery().eq(AttentionDevice::getAid, attentionId));

        // 把这个分组和分组设备绑定关系直接删除掉
        attentionMapper.deleteById(attentionId);
        attentionDeviceMapper.delete(Wrappers.<AttentionDevice>lambdaQuery().eq(AttentionDevice::getAid, attentionId));

        // 判断每一个设备还有没有跟其他分组绑定，如果没有了，就把设备的关注字段重置为取消关注
//        for (AttentionDevice attentionDevice : attentionDevices) {
//            int did = attentionDevice.getDid();
//            List<AttentionDevice> otherBinds = attentionDeviceMapper.selectList(Wrappers.<AttentionDevice>lambdaQuery().eq(AttentionDevice::getDid, did));
//            if (CollectionUtils.isEmpty(otherBinds)) {
//                Device device = new Device();
//                device.setId((long) did);
//                device.setAttention(0);
//                deviceMapper.updateById(device);
//            }
//        }

        return JsonResult.success();
    }

    @Override
    public JsonResult attentionBindDevice(Integer attentionId, String dids, Integer type) {
        String[] split = dids.split(",");
        if (type == 1) {
            // 1是转移，转移的话，就先把这些设备的绑定关系删掉
            List<String> strings = Arrays.asList(split);
            List<Long> didsLongArray = strings.stream().mapToLong(Long::parseLong).boxed().collect(Collectors.toList());
            attentionDeviceMapper.delete(Wrappers.<AttentionDevice>lambdaQuery().in(AttentionDevice::getDid, didsLongArray));
        }

        // 先查有没有，有就不添加了，没有就添加
        List<AttentionDevice> attentionDevices = new ArrayList<>();
        for (String str : split) {
            int did = Integer.parseInt(str);
            AttentionDevice isExist = attentionDeviceMapper.selectOne(Wrappers.<AttentionDevice>lambdaQuery()
                    .eq(AttentionDevice::getAid, attentionId)
                    .eq(AttentionDevice::getDid, did));
            if (isExist == null) {
                AttentionDevice attentionDevice = new AttentionDevice();
                attentionDevice.setAid(attentionId);
                attentionDevice.setDid(did);
                attentionDevices.add(attentionDevice);
            }
        }
        attentionDeviceMapper.addAll(attentionDevices);

        try {
            // 线程休眠1秒，解决前端页面数据刷新问题
            Thread.sleep(1000);
        } catch (InterruptedException exception) {
            exception.printStackTrace();
        }

        return JsonResult.success();
    }

    @Override
    public JsonResult listAttentions() {
        // 查询所有关注目录
        List<Attention> attentions = attentionMapper.selectList(null);
        List<AttentionVO> vos = new ArrayList<>();
        if (attentions.size() != 0) {
            for (Attention attention : attentions) {
                AttentionVO vo = new AttentionVO();
                BeanUtils.copyProperties(attention, vo);
                vos.add(vo);
            }
        }
        JsonResult jsonResult = JsonResult.success();
        jsonResult.setData(vos);
        jsonResult.setTotal(vos.size());
        return jsonResult;
    }

    @Override
    public JsonResult listAttentionAndDevices() {
        TokenUser tokenUser = StpLoginUserUtil.getTokenUser();
        if (tokenUser == null) {
            throw new ApiException(JsonResultEnum.FAIL, "无法获取登录用户信息，请重试");
        }
        Long userId = tokenUser.getUserId();
        // 查询对应用户的所有关注目录
        List<Attention> attentions = attentionMapper.selectList(Wrappers.<Attention>lambdaQuery().eq(Attention::getUid, userId));
        if (attentions.size() == 0) {
            JsonResult jsonResult = JsonResult.fail();
            jsonResult.setData("没有关注列表信息");
            return jsonResult;
        }
        List<AttentionVO> vos = new ArrayList<>();
        for (Attention attention : attentions) {
            AttentionVO vo = new AttentionVO();
            BeanUtils.copyProperties(attention, vo);
            vos.add(vo);
        }
        List<Integer> aids = vos.stream().map(AttentionVO::getId).collect(Collectors.toList());
        // 查询所有的目录设备绑定信息
        List<AttentionDevice> attentionDevices = attentionDeviceMapper
                .selectList(Wrappers.<AttentionDevice>lambdaQuery().in(AttentionDevice::getAid, aids));
        if (attentionDevices.size() == 0) {
            JsonResult jsonResult = JsonResult.success();
            jsonResult.setData(vos);
            jsonResult.setTotal(vos.size());
            return jsonResult;
        }
        Map<Integer, List<AttentionDevice>> aidMap = attentionDevices.stream().collect(Collectors.groupingBy(AttentionDevice::getAid));

        // 获取设备的通道信息并组织成map
        List<Integer> dids1 = attentionDevices.stream().mapToInt(AttentionDevice::getDid).boxed().distinct().collect(Collectors.toList());
        if (dids1.size() == 0) {
            JsonResult jsonResult = JsonResult.success();
            jsonResult.setData(vos);
            jsonResult.setTotal(vos.size());
            return jsonResult;
        }
        List<String> deviceIds = deviceMapper.listDeviceIdsByDids(dids1);
        if (deviceIds.size() == 0) {
            JsonResult jsonResult = JsonResult.success();
            jsonResult.setData(vos);
            jsonResult.setTotal(vos.size());
            return jsonResult;
        }
        List<DeviceChannel> deviceChannels = deviceChannelMapper.queryAllByDeviceIds(deviceIds);
        Map<String, List<DeviceChannel>> deviceChannelMap = null;
        if (deviceChannels.size() != 0) {
            deviceChannelMap = deviceChannels.stream().collect(Collectors.groupingBy(DeviceChannel::getDeviceId));
        }

        for (AttentionVO vo : vos) {
            Integer attentionId = vo.getId();
            // 获取这个目录下关注的设备
            List<AttentionDevice> attentionDeviceList = aidMap.get(attentionId);
            if (attentionDeviceList != null && attentionDeviceList.size() != 0) {
                List<Integer> dids = attentionDeviceList.stream().map(AttentionDevice::getDid).collect(Collectors.toList());
                List<Device> devices = deviceMapper.selectBatchIds(dids);
                List<DeviceVO> deviceVOS = new ArrayList<>();
                for (Device device : devices) {
                    DeviceVO deviceVO = new DeviceVO();
                    BeanUtils.copyProperties(device, deviceVO);
                    if (deviceChannelMap != null && deviceChannelMap.size() != 0) {
                        List<DeviceChannel> deviceChannelList = deviceChannelMap.get(device.getDeviceId());
                        deviceVO.setDeviceChannels(deviceChannelList);
                    }
                    String rdsInfo = jedisClusterBSJ.get(RedisConstant.REDIS_DEVICE_INFO + deviceVO.getDeviceId());
                    if (!StringUtil.isEmpty(rdsInfo)) {
                        RedisDeviceInfo redisDeviceInfo = JSON.parseObject(rdsInfo, RedisDeviceInfo.class);
                        deviceVO.setOnline(redisDeviceInfo.getOnline());
                        deviceVO.setFault(redisDeviceInfo.getFault());
                    } else {
                        deviceVO.setOnline(Constants.DEVICE_OFFLINE);
                    }
                    deviceVOS.add(deviceVO);
                }
                vo.setDeviceVOS(deviceVOS);

            }
        }
        JsonResult jsonResult = JsonResult.success();
        jsonResult.setData(vos);
        jsonResult.setTotal(vos.size());
        return jsonResult;
    }

    @Override
    public JsonResult copy(AttentionDTO attentionDTO) {
        QueryWrapper<Attention> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("attention_name", attentionDTO.getAttentionName());
        Attention attention1 = attentionMapper.selectOne(queryWrapper);
        if (attention1 != null) {
            throw new ApiException(JsonResultEnum.PARAM_ERROR, "名称重复，不能添加");
        }

        Attention attention = new Attention();
        BeanUtils.copyProperties(attentionDTO, attention);
        if (attention.getUid() == null) {
            TokenUser tokenUser = StpLoginUserUtil.getTokenUser();
            if (tokenUser == null) {
                throw new ApiException(JsonResultEnum.FAIL, "无法获取登录用户信息，请重试");
            }
            attention.setUid(tokenUser.getUserId().intValue());

        }
        // 先新增一个目录
        attentionMapper.insert(attention);

        Integer newId = attention.getId();
        if (newId == null) {
            throw new ApiException(JsonResultEnum.FAIL, "系统繁忙");
        }
        // 然后在关联表里添加目录和设备的绑定信息
        String dids = attentionDTO.getDids();
        String[] split = dids.split(",");
        List<String> strings = Arrays.asList(split);
        List<AttentionDevice> attentionDevices = new ArrayList<>();
        for (String str : split) {
            int did = Integer.parseInt(str);
            AttentionDevice attentionDevice = new AttentionDevice();
            attentionDevice.setAid(newId);
            attentionDevice.setDid(did);
            attentionDevices.add(attentionDevice);
        }
        attentionDeviceMapper.addAll(attentionDevices);

        try {
            // 线程休眠1秒，解决前端页面数据刷新问题
            Thread.sleep(1000);
        } catch (InterruptedException exception) {
            exception.printStackTrace();
        }

        return JsonResult.success();

    }

    @Override
    public JsonResult cancelInGroup(Long aid, Long did) {
        // 在分组中取消关注，删除对应分组和设备的绑定关系，不影响其他
        attentionDeviceMapper.delete(Wrappers.<AttentionDevice>lambdaQuery()
                .eq(AttentionDevice::getAid, aid)
                .eq(AttentionDevice::getDid, did));

        // 判断该设备是否和其他分组有绑定关系，如果没有了，就修改设备的关注字段为0（未关注）
//        List<AttentionDevice> attentionDevices = attentionDeviceMapper
//                .selectList(Wrappers.<AttentionDevice>lambdaQuery().eq(AttentionDevice::getDid, did));
//        if (CollectionUtils.isEmpty(attentionDevices)) {
//            Device device = new Device();
//            device.setId(did);
//            device.setAttention(0);
//            deviceMapper.updateById(device);
//        }
        try {
            // 线程休眠1秒，解决前端页面数据刷新问题
            Thread.sleep(1000);
        } catch (InterruptedException exception) {
            exception.printStackTrace();
        }

        return JsonResult.success();
    }

    @Override
    public JsonResult listUserAttentionDeviceIds() {
        JsonResult jsonResult = JsonResult.success();
        TokenUser tokenUser = StpLoginUserUtil.getTokenUser();
        if (tokenUser == null) {
            throw new ApiException(JsonResultEnum.FAIL, "无法获取登录用户信息，请重试");
        }
        Long userId = tokenUser.getUserId();

        List<Integer> ids = new ArrayList<>();
        List<Attention> attentions = attentionMapper.selectList(Wrappers.<Attention>lambdaQuery().eq(Attention::getUid, userId));
        if (CollectionUtils.isEmpty(attentions)) {
            jsonResult.setData(ids);
            return jsonResult;
        }
        List<Integer> attentionIds = attentions.stream().mapToInt(Attention::getId).boxed().collect(Collectors.toList());

        List<AttentionDevice> attentionDevices = attentionDeviceMapper.selectList(Wrappers.<AttentionDevice>lambdaQuery()
                .in(AttentionDevice::getAid, attentionIds));
        if (CollectionUtils.isEmpty(attentionDevices)) {
            jsonResult.setData(ids);
            return jsonResult;
        }

        List<Integer> dids = attentionDevices.stream().mapToInt(AttentionDevice::getDid).boxed().distinct().collect(Collectors.toList());
        jsonResult.setData(dids);
        return jsonResult;
    }


}
